package com.hanlink.dsp.ca.model.settings;

import com.hanlink.dsp.BtDspApplication;
import com.hanlink.dsp.DspSettings;
import com.hanlink.dsp.ca.model.channel.LevelChannel;
import com.hanlink.dsp.model.BaseSettings;
import com.hanlink.dsp.model.UploadThread;
import com.hanlink.dsp.util.BLog;
import com.hanlink.dsp.util.ByteUtil;
import com.hanlink.dsp.util.Constants;
import com.qztech.bluetooth.BluetoothClientManager;
import com.qztech.utils.YzDebug;

import org.xutils.DbManager;
import org.xutils.db.annotation.Column;
import org.xutils.db.annotation.Table;
import org.xutils.ex.DbException;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static com.hanlink.dsp.DspContext.BLE_WRITE_DELAY;
import static com.hanlink.dsp.DspContext.BLE_WRITE_DELAY_LARGE;

@Table(name = "_advance_settings")
public class AdvanceSettings extends BaseSettings {

    private float[] delay = new float[DspSettings.CHANNEL_LENGTH]; //所有
    @Column(name = "time_delay_val")
    private String delayVal = "";

    @Column(name = "_total_vol")
    private int totalVol = Constants.MAX_VOL;
    @Column(name = "_mute")
    private int mute = 0;
    @Column(name = "_last_channel")
    private int lastChannel = 0;


    private final List<LevelChannel> mChannels;

    public AdvanceSettings() {
        super();
        mChannels = new ArrayList<>();
    }

    @Override
    public void resetData() {
        Arrays.fill(delay,0);
        delayVal = Arrays.toString(delay);
        totalVol = Constants.MAX_VOL;
        mute = 0;
        lastChannel = 0;
        for (LevelChannel channel : mChannels) {
            channel.resetData();
        }
    }

    public void getChannels(DbManager db) throws DbException {
        List<LevelChannel> channels = null;
        if (db != null){
            channels = db.selector(LevelChannel.class).where("settings_id", "=", this.id).orderBy("channel").findAll();
        }
        YzDebug.d("getChannels LevelChannels" + (channels == null ?" empty ":("size:"+ channels.size())));
        if (channels == null || channels.size() <= 0) {
            channels = new ArrayList<>();
            LevelChannel lc  = null;
            for (int i = 0; i < DspSettings.CHANNEL_LENGTH; i++) {
                lc = new LevelChannel(i);
                lc.setSettingsId(id);
                channels.add(lc);
            }
        }
        this.setChannel(channels);
    }

    public List<LevelChannel> getChannel() {
        return mChannels;
    }

    public LevelChannel getChannelByIndex(int index) {
        if (index < 0 || index >=mChannels.size())
            return null;
        return mChannels.get(index);
    }

    public void setChannelValue(int index, int value) {
        if (this.mChannels == null || this.mChannels.size() <= 0) return;
        mChannels.get(index).setVal(value);
    }

    public void setChannelMute(int index, int mute) {
        if (this.mChannels == null || this.mChannels.size() <= 0) return;
        mChannels.get(index).setMute(mute);
    }

    public int setChannelChecked(int index, int checked, boolean grouping) {
        if (this.mChannels == null || this.mChannels.size() <= 0) return -1;
        int baseIndex = -1;
        LevelChannel levelChannel = mChannels.get(index);
        if (grouping && levelChannel.getLinked() == 1) {
            baseIndex = getBaseIndex();
        }
        levelChannel.setChecked(checked);
        levelChannel.sendCmd();
        return baseIndex;
    }

    public int getBaseIndex() {
        if (this.mChannels == null || this.mChannels.size() <= 0) return -1;
        int baseIndex = -1;
        for (int i = 0; i < mChannels.size(); i++) {
            LevelChannel c = mChannels.get(i);
            if (c.getLinked() == 1) {
                baseIndex = i;
                break;
            }
        }
        return baseIndex;
    }

    public void setChannel(List<LevelChannel> channels) {
        synchronized (mChannels){
            mChannels.clear();
            mChannels.addAll(channels);
            for (LevelChannel channel : mChannels) {
                channel.setSettingsId(this.id);
            }
        }
    }

    public float[] getDelay() {
        return delay;
    }

    public String getDelayVal() {
        return delayVal;
    }

    public void setDelayVal(String delayVal) {
        this.delayVal = delayVal;
        if (delayVal == null || "".equals(delayVal)) return;
        String[] tempGain = delayVal.replace("[", "").replace("]", "").split(",");
        try {
            for (int i = 0; i < tempGain.length; i++) {
                this.delay[i] = Float.parseFloat(tempGain[i].trim());
            }
        } catch (Exception ex) {
            System.out.println("ERROR:" + ex);
        }
    }

    public float getDelayValue(int index) {
        if (delay == null || delay.length <= 0 || index > delay.length) return 0;
        return delay[index];
    }

    public void setDelayValue(int index, float value) {
        if (delay == null || delay.length <= 0) {
            delay = new float[DspSettings.CHANNEL_LENGTH];
        }
        delay[index] = value;
        delayVal = Arrays.toString(delay);
    }

    public int getTotalVol() {
        return totalVol;
    }

    public void setTotalVol(int totalVol) {
        if (totalVol > Constants.MAX_VOL) totalVol = Constants.MAX_VOL;
        this.totalVol = totalVol;
    }

    public int getMute() {
        return mute;
    }

    public void setMute(int mute) {
        this.mute = mute;
    }

    public int getLastChannel() {
        return lastChannel;
    }


    public void setLastChannel(int lastChannel) {
        this.lastChannel = lastChannel;
    }


    @Override
    public String toString() {
        return "AdvanceSettings{" +
                "delay=" + Arrays.toString(delay) +
                ", delayVal='" + delayVal + '\'' +
                ", totalVol=" + totalVol +
                ", mute=" + mute +
                ", lastChannel=" + lastChannel +
                ", channel=" + mChannels +
                '}';
    }

    /**
     * 发送延迟
     *
     * @param index
     */
    public void sendTimeDelayCmd(int index) {
        byte[] buffer = getTimeDelayBuffer(index);
        BLog.d("timeDelay", ByteUtil.bytesToHexString(buffer));
        BluetoothClientManager.getInstance(BtDspApplication.getInstance()).write(buffer);
    }

    public byte[] getTimeDelayBuffer(int index) {
        byte[] buffer = new byte[]{(byte) 0xAA, (byte) 0x55, (byte) 0xCC, (byte) 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
        buffer[3] = (byte) (0xC1 + index);
        buffer[4] = (byte) ((int) (delay[index] * 100) >> 8 & 0xff);
        buffer[5] = (byte) ((int) (delay[index] * 100) & 0xff);
        return buffer;
    }

    public void sendAllTimeDelayCmd() {
        for (int i = 0; i < delay.length; i++) {
            sendTimeDelayCmd(i);
            try {
                if (i % 5 == 0) {
                    Thread.sleep(BLE_WRITE_DELAY_LARGE);
                } else {
                    Thread.sleep(BLE_WRITE_DELAY);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 发送总音量
     *
     * @param val
     * @param isMute
     */
    public void sendTotalVolCmd(int val, boolean isMute) {
        byte[] buffer = getTotalVolBuffer(val, isMute);
        BLog.d("totalVol", ByteUtil.bytesToHexString(buffer));
        BluetoothClientManager.getInstance(BtDspApplication.getInstance()).write(buffer);
    }

    public byte[] getTotalVolBuffer(int val, boolean isMute) {
        setMute(isMute ? 1 : 0);
        setTotalVol(val);
        byte[] buffer = new byte[]{(byte) 0xAA, (byte) 0x55, (byte) 0xEE, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
        if (mute == 1) {
            buffer[3] = (byte) 0x01;
        } else {
            buffer[3] = (byte) 0x00;
        }
        int volume = Math.abs(val - Constants.MAX_VOL) * 10;
        buffer[4] = (byte) (volume >> 8 & 0xff);
        buffer[5] = (byte) (volume & 0xff);
        return buffer;
    }

    public byte[] getCmdData() {
        //total vol
        byte[] totalVolBuffer = new byte[]{(byte) 0xAA, (byte) 0x11, (byte) 0xC0, 0x00, 0x00, 0x00, (byte) 0xEE, 0x55};
        if (mute == 1) {
            totalVolBuffer[3] = (byte) 0x00;
            totalVolBuffer[4] = (byte) 0x11;
        } else {
            totalVolBuffer[3] = (byte) Math.abs(totalVol - Constants.MAX_VOL);
            totalVolBuffer[4] = (byte) 0x00;
        }
        //level
        int size = mChannels.size();
        for (int i = 0; i < size; i++) {
            LevelChannel levelChannel = mChannels.get(i);
            byte[] buffer = levelChannel.getCmdData();
            buffer[2] = (byte) (0xC1 + i);
        }

        //timeDelay
        for (int i = 0, len = delay.length; i < len; i++) {
            byte[] safeAddress = new byte[]{(byte) 0xAA, (byte) 0x22, (byte) (0xC1 + i), 0x00, 0x00, 0x00, (byte) 0xEE, 0x55};
            safeAddress[3] = (byte) (((int) delay[i] * 10 >> 8) & 0xff);
            safeAddress[4] = (byte) (((int) delay[i] * 10) & 0xff);
        }
        // FIXME: 2017/8/7
        return totalVolBuffer;
    }


    public AdvanceSettings copy(){
        final AdvanceSettings as = new AdvanceSettings();
        System.arraycopy(delay,0, as.delay,0, DspSettings.CHANNEL_LENGTH);
        as.delayVal = delayVal;
        as.totalVol = totalVol;
        as.mute = mute;
        as.lastChannel = lastChannel;
        for (LevelChannel channel : mChannels) {
            as.mChannels.add(channel.copy());
        }

        return as;
    }

    public void copyIdFromSrc(AdvanceSettings advanceSettings) {
        this.id = advanceSettings.id;
        this.refId = advanceSettings.refId;
        for (LevelChannel dst : mChannels) {
            for (LevelChannel src : advanceSettings.mChannels) {
                if (src.getChannel() == dst.getChannel()){
                    dst.setId(src.getId());
                    dst.setSettingsId(src.getSettingsId());
                }

            }
        }
    }
}
